package org.apache.commons.io;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class IOUtils {
	public static final int EOF = -1;
	private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
	public static final String LINE_SEPARATOR;
	static {
		// avoid security issues
		final StringWriter buf = new StringWriter(4);
		final PrintWriter out = new PrintWriter(buf);
		out.println();
		LINE_SEPARATOR = buf.toString();
		out.close();
	}

	public static void closeQuietly(final Closeable closeable) {
		try {
			if (closeable != null) {
				closeable.close();
			}
		} catch (final IOException ioe) {
			// ignore
		}
	}
    public static void closeQuietly(final Closeable... closeables) {
        if (closeables == null) {
            return;
        }
        for (final Closeable closeable : closeables) {
            closeQuietly(closeable);
        }
    }

	public static List<String> readLines(final InputStream input,
			final Charset encoding) throws IOException {
		final InputStreamReader reader = new InputStreamReader(input,
				Charsets.toCharset(encoding));
		return readLines(reader);
	}

	public static List<String> readLines(final InputStream input,
			final String encoding) throws IOException {
		return readLines(input, Charsets.toCharset(encoding));
	}

	public static List<String> readLines(final Reader input) throws IOException {
		final BufferedReader reader = toBufferedReader(input);
		final List<String> list = new ArrayList<String>();
		String line = reader.readLine();
		while (line != null) {
			list.add(line);
			line = reader.readLine();
		}
		return list;
	}

	public static BufferedReader toBufferedReader(final Reader reader) {
		return reader instanceof BufferedReader ? (BufferedReader) reader
				: new BufferedReader(reader);
	}

	public static byte[] toByteArray(final InputStream input)
			throws IOException {
		final ByteArrayOutputStream output = new ByteArrayOutputStream();
		copy(input, output);
		return output.toByteArray();
	}

	public static int copy(final InputStream input, final OutputStream output)
			throws IOException {
		final long count = copyLarge(input, output);
		if (count > Integer.MAX_VALUE) {
			return -1;
		}
		return (int) count;
	}

	public static long copyLarge(final InputStream input,
			final OutputStream output) throws IOException {
		return copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static long copy(final InputStream input, final OutputStream output,
			final int bufferSize) throws IOException {
		return copyLarge(input, output, new byte[bufferSize]);
	}

	public static long copyLarge(final InputStream input,
			final OutputStream output, final byte[] buffer) throws IOException {
		long count = 0;
		int n = 0;
		while (EOF != (n = input.read(buffer))) {
			output.write(buffer, 0, n);
			count += n;
		}
		return count;
	}

	public static void writeLines(final Collection<?> lines,
			final String lineEnding, final OutputStream output,
			final String encoding) throws IOException {
		writeLines(lines, lineEnding, output, Charsets.toCharset(encoding));
	}

	public static void writeLines(final Collection<?> lines, String lineEnding,
			final OutputStream output, final Charset encoding)
			throws IOException {
		if (lines == null) {
			return;
		}
		if (lineEnding == null) {
			lineEnding = LINE_SEPARATOR;
		}
		final Charset cs = Charsets.toCharset(encoding);
		for (final Object line : lines) {
			if (line != null) {
				output.write(line.toString().getBytes(cs));
			}
			output.write(lineEnding.getBytes(cs));
		}
	}
}
